<?php

class Soul_Db_Driver_Mysql extends Soul_Db_Driver_Base {

	private $_link = NULL;
	private $_isTransaction = FALSE;

	public function __construct($server = NULL, $database = NULL, $username = NULL, $password = NULL){
		parent::__construct($server, $database, $username, $password);
	}

	public function __destruct(){
		$this->_link = NULL;
		$this->_isTransaction = FALSE;
	}

	public function isConnected() {
		return $this->_link ? TRUE : FALSE;
	}

	public function isTransaction() {
		return $this->_isTransaction;
	}

	public function escapeString(&$value) {
		if(is_array($value)){
			foreach($value as &$v){
				$v = mysql_real_escape_string($v);
			}
			return $value;
		}
		return mysql_real_escape_string($value);
	}

    public function setSql($sql, $params = array()) {
        $this->originSql = $sql;
        $this->boundSql = str_replace('{t}', Soul_Config::$dbTablePrefix, $this->originSql);
        if (is_array($params)) {
            preg_match_all('/(:[a-zA-Z]\w+)(:[isbad])?/', $this->boundSql, $matches);
            $paramNames = $matches[1];
            $paramTypes = $matches[2];
            for ($i = 0; $i < count($paramNames); $i++) {
                $n = substr($paramNames[$i], 1);
                $t = empty($paramTypes[$i]) ? 's' : substr($paramTypes[$i], 1);
                $v = $params[$n];
                if(is_null($v)){
                	$v = 'NULL';
                }else{
                	$escapeValue = $this->escapeString($v);
	                switch($t){
	                	case 'i':
                        case 'f':
	                		$v = $escapeValue;
	                		break;
	                	case 'a':
	                		$nv = array();
	                		foreach ($escapeValue as $sv) {
								$nv[] = "'".$sv."'";
	                    	}
	                    	$v = implode(',', $nv);
	                    	break;                  	
	                	default:
	                		$v = "'".$escapeValue."'";
	                		break;
	                }
                }
                $this->boundSql = str_replace($matches[0][$i], $v, $this->boundSql);
                
            }
        }
        return $this;
    }

	public function connect() {
		if (!$this->_link) {
			$this->_link = mysql_connect($this->getServer(), $this->getUsername(), $this->getPassword());
			if(!$this->_link){
				throw new Soul_Db_Exception(mysql_errno($this->_link) . ':' . mysql_errno($this->_link));
				 
			}
			$b = mysql_select_db($this->getDatabase(), $this->_link);
			if (!$b) {
				throw new Soul_Db_Exception(mysql_errno($this->_link) . ':' . mysql_errno($this->_link));
			}
		}
		return $this;
	}

	public function disconnect() {
		if ($this->_link) {
			mysql_close($this->_link);
			$this->_link = NULL;
		}
	}

	public function getInsertId() {
		return mysql_insert_id($this->_link);
	}

	public function beginTransaction() {
		if ($this->_isTransaction === FALSE) {
			$this->_link->autocommit(FALSE);
			$this->_isTransaction = TRUE;
		}
		return $this;
	}

	public function commitTransaction() {
		if ($this->_isTransaction) {
			$this->_link->commit();
			$this->_isTransaction = FALSE;
		}
		return $this;
	}

	public function rollbackTransaction() {
		if ($this->_isTransaction) {
			$this->_link->rollback();
			$this->_isTransaction = FALSE;
		}
		return $this;
	}

	public function execute() {
		mysql_query($this->_link, "SET NAMES '".Soul_Config::$dbEncoding."'");
		return mysql_query($this->_link, $this->boundSql);
	}
    
	public function executeBatch($sql, $split = ';') {
        $arr = explode(';', $sql);
        mysql_query($this->_link, "SET NAMES '".Soul_Config::$dbEncoding."'");
        try{
            $this->beginTransaction();
            foreach($arr as $str){
                if(!empty($str)){
                    mysql_query($this->_link, $str);
                }
            }
            $this->commitTransaction();
        }catch(Exception $ex){
            $this->rollbackTransaction();
            throw $ex;
        }
        return $this;
	}    

	public function getAffectedRows() {
		return $this->_link->affected_rows;
	}

	public function fetch() {
		$iter = $this->execute();
		$result = new Soul_Db_Result();
		while ($row = mysql_fetch_assoc($result)) {
			if(!Soul_Util_Enviroment::getMagicQuotesRuntime()){
				foreach($row as $name=>&$value){
					$value = stripslashes($value);
				}
			}
			$result->append($row);
		}
		$iter->close();
		return $result;
	}

	public function fetchLimit($limit, $offset) {
		if (!empty($limit) && $limit > 0) {
			$this->boundSql .= "\nLIMIT $offset,$limit";
		}
		return $this->fetch();
	}

}